import { useState, useEffect, useMemo, forwardRef, useImperativeHandle, useRef } from 'react'
import { Form, Select, Button, Col, Row, Tree, Flex, message, Tag, Space, Tooltip, Typography, Modal } from 'antd'
import { useQuery } from '@tanstack/react-query';
import { ModalForm, ProFormCheckbox, ProFormDependency, ProFormDigit, ProFormItem, ProFormSelect, ProFormText, ProFormTextArea } from "@ant-design/pro-components";
import { PlusCircleOutlined, DeleteOutlined, DownOutlined, QuestionCircleOutlined, SyncOutlined, LoadingOutlined } from '@ant-design/icons';
import { kafkaAll, kafkaConnect, kafkaConnectAdd, kafkaConnectDelete, kafkaConnectTest, kafkaConnectUpdate } from '@/api/sharing/kafka'

const keyColorMap = { hash: '#70b603', list: '#3aa8ff', set: '#8400ff', zset: '#ff0000', string: '#f59a23' }

const KafkaLeftPanel = forwardRef(({ currentSource, setCurrentSource }, ref) => {
  const [treeData, setTreeData] = useState([])
  const [activeLink, setActiveLink] = useState({})
  const [connecting, setConnecting] = useState(false)
  const [loadedKeys, setLoadedKeys] = useState([])
  const [loadingMap, setLoadingMap] = useState({})


  useImperativeHandle(ref, () => ({
    toConnect: () => {
      setConnecting(true)
      setTimeout(() => {
        toConnect()
      }, 1000)
    },
    toDelete: () => {
      setConnecting(true)
      setTimeout(() => {
        toConnect()
        setCurrentSource(null)
      }, 1000)
    }
  }))


  const { data: links, refetch, isFetching } = useQuery({
    queryKey: ['kafka-kafkaAll'],
    queryFn: () => {
      return kafkaAll().then((res) => {
        return res.result.map(item => ({ label: item.name, value: item.id, ...item }))
      })
    },
  })

  const onSelectChange = (_, option) => {
    setActiveLink(option)
  }
  /* 添加操作 */
  const toConnect = (link) => {
    const linkInfo = link.bootstrapServers ? link : activeLink
    setConnecting(true)
    setLoadedKeys([])
    kafkaConnect({ id: linkInfo.id }).then(res => {
      if (res.code === 200) {
        const data = Object.keys(res.result).filter(key => key !== 'clusterId').map((database) => {
          return {
            key: database.toString(),
            title: database.toString().charAt(0).toUpperCase() + database.toString().slice(1),
            count: res.result[database].num,
            selectable: false,
            children: res.result[database].result.map(key => ({
              title: key,
              key: database + '--' + key,
              database: database,
              brokerNum: res.result['broker'].num,
              connectInfo: { ...linkInfo },
              isLeaf: true
            }))
          }
        })
        setTreeData(data)
      } else {
        setCurrentSource(null)
        setTreeData([])
      }
    }).finally(() => {
      setConnecting(false)
    })

  }

  // 新增
  const handleConnectionSave = (values) => {
    if (values.id) {
      return kafkaConnectUpdate(values).then((res) => {
        if (res.code !== 200) return false
        refetch()
        setActiveLink({})
        message.success('修改成功')

        setTimeout(() => {
          setActiveLink(links.find(item => item.id === values.id))
        }, 200)
        return true
      })
    } else {
      return kafkaConnectAdd(values).then((res) => {
        if (res.code !== 200) return false
        setActiveLink(res.result)
        toConnect(res.result)
        refetch()
        message.success('新增成功')
        return true
      })
    }
  }

  // 新增key
  const handleAddDatabase = (values) => {
    return addRedisKey({ ...values, dataType: values.dataType.toLocaleUpperCase() }).then((res) => {
      if (res.code == 200) {
        let tree = [...treeData]
        let databaseItem = tree.find(item => item.key === values.database)
        if (databaseItem && !databaseItem.children.find(item => item.key === values.key)) {
          databaseItem.count = databaseItem.count + 1
        }
        setTreeData(tree)
        onLoadData({ key: values.database })
        message.success('新增成功')
        return true
      }
    })
  }

  const handleDeleteConnection = () => {
    Modal.confirm({
      title: '确定删除选中的连接吗？',
      onOk: () => {
        return kafkaConnectDelete({ id: activeLink.id }).then((res) => {
          if (res.code == 200) {
            setCurrentSource(null)
            setActiveLink({})
            refetch()
            message.success('删除成功')
            return true
          }
        })
      }
    })
  }


  return (
    <>
      <div className='left-panel-header'>
        <Flex>
          <Select value={activeLink.id} loading={isFetching} style={{ width: '100%' }} placeholder="请选请求方式" options={links} onChange={onSelectChange}></Select>
          <Button disabled={!activeLink.id} loading={connecting} style={{ width: '88px', flexShrink: 0, marginLeft: '10px' }} type="primary" onClick={toConnect}>
            连接
          </Button>
        </Flex>
        <Flex style={{ marginTop: '10px' }}>
          <Typography.Text style={{ lineHeight: '32px', paddingLeft: '10px', flex: 1, opacity: !activeLink.id ? 0 : 1 }} ellipsis={{ tooltip: activeLink.bootstrapServers }}>{activeLink.bootstrapServers}</Typography.Text>
          <Space>
            <span></span>
            <AddConnectionBtn onFinish={handleConnectionSave} />
            <AddConnectionBtn title="修改连接"
              initialValues={activeLink}
              onFinish={handleConnectionSave}
              trigger={<Button type="primary" disabled={!activeLink.id}>修改</Button>}
            />
            <Button disabled={!activeLink.id} type="primary" onClick={handleDeleteConnection} danger>删除</Button>
          </Space>
        </Flex>
      </div>

      <Tree
        showIcon
        treeData={treeData}
        titleRender={nodeData => {
          if (nodeData.isLeaf) {
            return nodeData.title
          } else {
            return <Flex justify='space-between' className='database-title' align='center'>
              <span>{`${nodeData.title}(${nodeData.count})`}</span>
              <Space className='database-btn'>
                <Button
                  type="text"
                  icon={<SyncOutlined />}
                  size="small"
                  onClick={() => {
                    toConnect()
                  }}
                />
                {/* <AddDatabaseBtn initialValues={{ id: activeLink.id, database: nodeData.key }} onFinish={handleAddDatabase} /> */}
              </Space>
            </Flex>
          }
        }}
        onSelect={(_, option) => {
          setCurrentSource({
            key: option.node.title,
            tag: option.node.tag,
            database: option.node.database,
            brokerNum: option.node.brokerNum,
            connectInfo: { ...option.node.connectInfo },
          })
        }}
      />
    </>
  )
})


// 新增database
const AddConnectionBtn = (props) => {
  const formRef = useRef()
  const handleTest = () => {
    kafkaConnectTest({ bootstrapServers: formRef.current.getFieldValue('bootstrapServers') }).then(res => {
      if (res.code === 200) {
        message.success('测试成功')
      }
    })
  }
  return (
    <ModalForm
      width={'600px'}
      formRef={formRef}
      trigger={<Button type="primary">新增</Button>}
      title="新增连接"
      modalProps={{ destroyOnClose: true }}
      grid={true}
      submitter={{
        render: (props, doms) => {
          return <Space><Button onClick={handleTest}>测试连接</Button>{doms}</Space>;
        },
      }}
      {...props}
    >
      <ProFormItem name="id" hidden />
      <ProFormText name="name" label="名称" placeholder="请输入名称" rules={[{ required: true, message: '名称不能为空' }]} />
      <ProFormText name="bootstrapServers" label="bootstrap servers" placeholder="请输入bootstrap servers" rules={[{ required: true, message: 'bootstrap servers不能为空' }]} />
    </ModalForm>
  )
}

// 新增database
const AddDatabaseBtn = (props) => {
  return (
    <ModalForm
      width={'600px'}
      trigger={
        <Tooltip title="添加新键">
          <Button
            type="text"
            icon={<PlusCircleOutlined />}
            size="small"
          />
        </Tooltip>
      }
      title="添加新键"
      modalProps={{ destroyOnClose: true }}
      grid={true}
      {...props}
    >
      <ProFormItem name="id" hidden />
      <ProFormItem name="database" hidden />
      <ProFormText name="key" label="键名" placeholder="请输入键名" rules={[{ required: true, message: '键名不能为空' }]} />
      <ProFormCheckbox name="serializer" fieldProps={{}} >
        <Space>
          <span>使用JDK序列化</span>
          <Tooltip overlayStyle={{ maxWidth: 400 }} placement='bottom' title={`JDK序列化说明： 默认作为 String 类型来序列化。
            若内容带有类型提示: 如 123♣java.lang.Long => 将转换为 Long 类型来序列化；
            若希望转换为复杂对象来序列化，则可以这样表示： ["java.util.ArrayList",
            [{"@class":"cn.com.bluemoon.invocationlab.admin.rpcpostman.model.erd.AesReqVo",
            "projectId":"2011yhfdsaa","opType":1,"value":898}]] => 将转换为为
            ArrayList<AesReqVo> 类型来序列化(如果能找到对应的class且class实现了Serializable接口)`}>
            <QuestionCircleOutlined />
          </Tooltip>
        </Space>
      </ProFormCheckbox>
      <ProFormSelect
        name="dataType"
        label="类型"
        placeholder="请选择类型"
        rules={[{ required: true, message: '类型不能为空' }]}
        options={[{ label: 'string', value: 'string' }, { label: 'list', value: 'list' }, { label: 'set', value: 'set' }, { label: 'zset', value: 'zset' }, { label: 'hash', value: 'hash' }]} />
      <ProFormDependency name={['dataType']}>
        {({ dataType }) => {
          if (dataType === 'hash') {
            return <ProFormText name="hashKey" label="键名" placeholder="请输入键名" rules={[{ required: true, message: '键名不能为空' }]} />
          } else if (dataType === 'zset') {
            return <ProFormDigit
              name="score"
              label="分数"
              fieldProps={{ min: 0, precision: 0 }}
              placeholder="请输入分数"
              rules={[{ required: true, message: '请输入分数' }]} />
          }
        }}
      </ProFormDependency>

      <ProFormTextArea name="value" label="键值" placeholder="请输入键值" rules={[{ required: true, message: '键值不能为空' }]} />
    </ModalForm>
  )
}

export default KafkaLeftPanel
